<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Relationship Types : DataMapper User Guide</title>

<style type='text/css' media='all'>@import url('../css/userguide.css');</style>
<link rel='stylesheet' type='text/css' media='all' href='../css/userguide.css' />

<meta http-equiv='expires' content='-1' />
<meta http-equiv= 'pragma' content='no-cache' />
<meta name='robots' content='all' />

</head>

<body>

<!-- START NAVIGATION -->
<div id="nav"><div id="nav_inner"></div></div>
<div id="nav2"><a name="top">&nbsp;</a><a id="nav_toggle" href="#"><img src="../images/nav_toggle_darker.jpg" width="154" height="43" border="0" title="Toggle Table of Contents" alt="Toggle Table of Contents" /></a></div>
<div id="masthead">
<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
<tr>
<td><h1>DataMapper</h1></td>
<td id="breadcrumb_right"><a href="toc.html">Table of Contents Page</a></td>
</tr>
</table>
</div>
<!-- END NAVIGATION -->

<!-- START BREADCRUMB -->
<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
<tr>
<td id="breadcrumb">
<a href="http://stensi.com/">DataMapper Home</a> &nbsp;&#8250;&nbsp;
<a href="../index.html">User Guide Home</a> &nbsp;&#8250;&nbsp;
Relationship Types
</td>
</tr>

</table>
<!-- END BREADCRUMB -->

<br clear="all" />


<!-- START CONTENT -->
<div id="content">


<h1>Relationship Types</h1>

<p>There are 3 different types of relationships objects can have with one another.  These are:</p>

<ul>
	<li>One to One</li>
	<li>One to Many</li>
	<li>Many to Many</li>
</ul>

<p>To describe these relationships, we will use the following Database tables as an example to work with:</p>


<h3>tools</h3>
<table cellpadding="0" cellspacing="1" border="0" class="tableborder">
<tr>
	<th>id</th>
	<th>name</th>
	<th>description</th>
</tr>
<tr>
	<td class="td">7</td>
	<td class="td">Small Red Hammer</td>
	<td class="td">Red hammer to hit things with, preferably nails.</td>
</tr>
<tr>
	<td class="td">8</td>
	<td class="td">Crowbar</td>
	<td class="td">Heavy crowbar, for busting open crates or zombie heads.</td>
</tr>
<tr>
	<td class="td">9</td>
	<td class="td">Axe</td>
	<td class="td">Nice shiny axe, for chopping down trees or inflated egos.</td>
</tr>
<tr>
	<td class="td">10</td>
	<td class="td">Drill</td>
	<td class="td">Large drill for breaking up large stones or doing delicate dentistry work (on giants).</td>
</tr>
<tr>
	<td class="td">11</td>
	<td class="td">Box of Nails</td>
	<td class="td">Yep, one box of nails is all we've got.</td>
</tr>
<tr>
	<td class="td">12</td>
	<td class="td">Big Hammer</td>
	<td class="td">Blacksmith's hammer for shaping metal into who knows what.</td>
</tr>
</table>

<h3>tools_workplaces</h3>
<table cellpadding="0" cellspacing="1" border="0" class="tableborder">
<tr>
	<th>id</th>
	<th>tool_id</th>
	<th>workplace_id</th>
</tr>
<tr>
	<td class="td">1</td>
	<td class="td">7</td>
	<td class="td">42</td>
</tr>
<tr>
	<td class="td">2</td>
	<td class="td">9</td>
	<td class="td">42</td>
</tr>
<tr>
	<td class="td">3</td>
	<td class="td">11</td>
	<td class="td">42</td>
</tr>
<tr>
	<td class="td">4</td>
	<td class="td">8</td>
	<td class="td">43</td>
</tr>
<tr>
	<td class="td">5</td>
	<td class="td">10</td>
	<td class="td">43</td>
</tr>
<tr>
	<td class="td">6</td>
	<td class="td">12</td>
	<td class="td">44</td>
</tr>
</table>

<h3>workplaces</h3>
<table cellpadding="0" cellspacing="1" border="0" class="tableborder">
<tr>
	<th>id</th>
	<th>location</th>
</tr>
<tr>
	<td class="td">42</td>
	<td class="td">Timber Mill</td>
</tr>
<tr>
	<td class="td">43</td>
	<td class="td">Old Stone Quarry</td>
</tr>
<tr>
	<td class="td">44</td>
	<td class="td">Blacksmith Hut</td>
</tr>
</table>

<h3>workers_workplaces</h3>
<table cellpadding="0" cellspacing="1" border="0" class="tableborder">
<tr>
	<th>id</th>
	<th>worker_id</th>
	<th>workplace_id</th>
</tr>
<tr>
	<td class="td">1</td>
	<td class="td">1</td>
	<td class="td">44</td>
</tr>
<tr>
	<td class="td">2</td>
	<td class="td">2</td>
	<td class="td">42</td>
</tr>
<tr>
	<td class="td">3</td>
	<td class="td">3</td>
	<td class="td">43</td>
</tr>
</table>

<h3>workers</h3>
<table cellpadding="0" cellspacing="1" border="0" class="tableborder">
<tr>
	<th>id</th>
	<th>firstname</th>
	<th>lastname</th>
</tr>
<tr>
	<td class="td">1</td>
	<td class="td">Fred</td>
	<td class="td">Smith</td>
</tr>
<tr>
	<td class="td">2</td>
	<td class="td">Jayne</td>
	<td class="td">Doe</td>
</tr>
<tr>
	<td class="td">3</td>
	<td class="td">Joe</td>
	<td class="td">Public</td>
</tr>
</table>

<h3>skills_workers</h3>
<table cellpadding="0" cellspacing="1" border="0" class="tableborder">
<tr>
	<th>id</th>
	<th>skill_id</th>
	<th>worker_id</th>
</tr>
<tr>
	<td class="td">1</td>
	<td class="td">22</td>
	<td class="td">1</td>
</tr>
<tr>
	<td class="td">2</td>
	<td class="td">27</td>
	<td class="td">1</td>
</tr>
<tr>
	<td class="td">3</td>
	<td class="td">23</td>
	<td class="td">2</td>
</tr>
<tr>
	<td class="td">4</td>
	<td class="td">25</td>
	<td class="td">2</td>
</tr>
<tr>
	<td class="td">5</td>
	<td class="td">25</td>
	<td class="td">3</td>
</tr>
<tr>
	<td class="td">6</td>
	<td class="td">26</td>
	<td class="td">3</td>
</tr>
<tr>
	<td class="td">7</td>
	<td class="td">27</td>
	<td class="td">3</td>
</tr>
</table>

<h3>skills</h3>
<table cellpadding="0" cellspacing="1" border="0" class="tableborder">
<tr>
	<th>id</th>
	<th>name</th>
</tr>
<tr>
	<td class="td">22</td>
	<td class="td">Blacksmith</td>
</tr>
<tr>
	<td class="td">23</td>
	<td class="td">Carpentry</td>
</tr>
<tr>
	<td class="td">24</td>
	<td class="td">Cabinet Maker</td>
</tr>
<tr>
	<td class="td">25</td>
	<td class="td">Builder</td>
</tr>
<tr>
	<td class="td">26</td>
	<td class="td">Stonemason</td>
</tr>
<tr>
	<td class="td">27</td>
	<td class="td">Zombie Slayer</td>
</tr>
</table>

<br />

<p>If you've read <a href="database.html">Database Tables</a>, you will recognise that <b>tools</b>, <b>workplaces</b>, <b>workers</b> and <b>skills</b> are all normal tables.  These are the tables that you would create a DataMapper model for, in order to tranform them into objects.</p>
<p>The other tables, being <b>tools_workplaces</b>, <b>workers_workplaces</b> and <b>skills_workers</b>, are the joining tables which hold the relationship records between the normal tables.</p>

<h2>One to One</h2>

<p>One to One relationships occur when there is exactly one record in the first table that corresponds to exactly one record in the related table.</p>

<p>For example, a worker can be assigned to only one workplace and a workplace can have only one worker. From the tables above we can see that:</p>

<p><b>Fred Smith</b> works at the <b>Blacksmith Hut</b>.<br />
<b>Jayne Doe</b> works at the <b>Timber Mill</b>.<br />
<b>Joe Public</b> works at the <b>Old Stone Quarry</b>.</p>

<p>Only Fred is allowed to work at the Blacksmith Hut. Similarly for the others, they can work only at their own workplace and no one else can work there. Sure, it's not very efficient to have one worker per workplace but it suits for this example.</p>



<h2>One to Many</h2>

<p>One to Many relationships occur when each record in the first table has many linked records in the related table but each record in the related table has only one corresponding record in the first table.</p>

<p>For example, a workplace can be equipped with many tools but a tool can be in only one workplace. From the tables above we can see that:</p>

<p>The <b>Blacksmith Hut</b> has the <b>Big Hammer</b>.<br/>
The <b>Timber Mill</b> has the <b>Small Red Hammer</b>, <b>Axe</b> and <b>Box of Nails</b>.<br/>
The <b>Old Stone Quarry</b> has the <b>Crowbar</b> and <b>Drill</b>.</p>




<h2>Many to Many</h2>

<p>Many to Many relationships occur when each record in the first table has many linked records in the related table and vice-versa.</p>

<p>For example, a worker can have many skills and a skill can have many workers listed with it. From the tables above we can see that:</p>

<p><b>Fred Smith</b> has the <b>Blacksmith</b> and <b>Zombie Slayer</b> skills.<br/>
<b>Jayne Doe</b> has the <b>Carpentry</b> and <b>Builder</b> skills.<br/>
<b>Joe Public</b> has the <b>Builder</b>, <b>Stonemason</b> and <b>Zombie Slayer</b> skills.</p>

<p>So we can see that each of the workers have multiple skills, and in the case of the <b>Builder</b> and <b>Zombie Slayer</b> skills, we see there are multiple workers who have them.</p>
<p>The <b>Builder</b> skill is listed against <b>Jayne Doe</b> and <b>Joe Public</b>.<br />
The <b>Zombie Slayer</b> skill is listed against <b>Fred Smith</b> and <b>Joe Public</b>.</p>


<h2>Self Referencing Relationships</h2>

<p>DataMapper is smart enough to allow self referencing relationships.  A self referencing relationship is where you have a model with a relationship to itself.  For example, let's say we have an <b>employees</b> table with different types of employees, these being <strong>Manager</strong>, <strong>Supervisor</strong> and <strong>Underling</strong>.</p>

<p>Their relationships are:</p>

<ul>
	<li>A Manager manages Many Supervisors.</li>
	<li>A Supervisor has One Manager.</li>
	<li>A Supervisor supervises Many Underlings.</li>
	<li>An Underling has One Supervisor.</li>
</ul>

<p>As we have three different types of employees, each with different types of relationships, we need to create a DataMapper model for each of them. However, since they are all employees, they will have a lot in common, so we'll make a generic Employee model that they'll each extend from, allowing us to manage the validation rules and other common methods more easily.</p>

<h3>Employee model</h3>
<textarea class="textarea" style="width:100%" cols="50" rows="20">
<?php

/**
 * Employee Class (contains self referencing relationships)
 *
 * Transforms employees table into a Employee object.
 *
 * @licence 	MIT Licence
 * @category	Models
 * @author  	Simon Stenhouse
 * @link    	http://stensi.com
 */
class Employee extends DataMapper
{
	var $table = "employees";

	var $validation = array(
		array(
			'field' => 'first_name',
			'label' => 'First Name',
			'rules' => array('required', 'trim', 'alpha', 'max_length' => '40', 'unique_pair' => 'last_name')
		),
		array(
			'field' => 'last_name',
			'label' => 'Last Name',
			'rules' => array('required', 'trim', 'alpha', 'max_length' => '40', 'unique_pair' => 'first_name')
		),
		array(
			'field' => 'position',
			'label' => 'Position',
			'rules' => array('required', 'valid_match' => array('Manager', 'Supervisor', 'Underling'))
		)
	);

	/**
	 * Constructor
	 *
	 * Initialize DataMapper.
	 */
	function Employee()
	{
		parent::DataMapper();
	}

	// --------------------------------------------------------------------
	
	/**
	 * Full Name
	 *
	 * Returns the employees full name.
	 *
	 * @access	public
	 * @return	string
	 */
	function full_name()
	{
		return $this->first_name . ' ' . $this->last_name;
	}
}

/* End of file employee.php */
/* Location: ./application/models/employee.php */
</textarea>

<p>Now we'll make our different types of employees, extending the generic Employee model, thus making them all use the employees table.  As their <kbd>$has_many</kbd> and <kbd>$has_one</kbd> settings reference each other, we end up with a self referencing relationship.</p>

<h3>Manager model</h3>
<textarea class="textarea" style="width:100%" cols="50" rows="20">
<?php

/**
 * Manager Class (contains self referencing relationships)
 *
 * Transforms employees table into a Manager object.
 *
 * @licence 	MIT Licence
 * @category	Models
 * @author  	Simon Stenhouse
 * @link    	http://stensi.com
 */
class Manager extends Employee
{
	var $has_many = array("supervisor");

	/**
	 * Constructor
	 *
	 * Initialize DataMapper.
	 */
	function Manager()
	{
		parent::Employee();
	}

	// --------------------------------------------------------------------

	/**
	 * Get (overload)
	 *
	 * Get objects.
	 *
	 * @access	public
	 * @param	int or array
	 * @return	bool
	 */
	function get($limit = NULL, $offset = NULL)
	{
		$position = empty($this->position) ? 'Manager' : $this->position;

		$this->where('position', $position);

		return parent::get($limit, $offset);
	}
}

/* End of file manager.php */
/* Location: ./application/models/manager.php */
</textarea>

<h3>Supervisor model</h3>
<textarea class="textarea" style="width:100%" cols="50" rows="20">
<?php

/**
 * Supervisor Class (contains self referencing relationships)
 *
 * Transforms employees table into a Supervisor object.
 *
 * @licence 	MIT Licence
 * @category	Models
 * @author  	Simon Stenhouse
 * @link    	http://stensi.com
 */
class Supervisor extends Employee
{
	var $has_one = array("manager");
	var $has_many = array("underling");

	/**
	 * Constructor
	 *
	 * Initialize DataMapper.
	 */
	function Supervisor()
	{
		parent::Employee();
	}

	// --------------------------------------------------------------------

	/**
	 * Get (overload)
	 *
	 * Get objects.
	 *
	 * @access	public
	 * @param	int or array
	 * @return	bool
	 */
	function get($limit = NULL, $offset = NULL)
	{
		$position = empty($this->position) ? 'Supervisor' : $this->position;

		$this->where('position', $position);

		return parent::get($limit, $offset);
	}
}

/* End of file supervisor.php */
/* Location: ./application/models/supervisor.php */
</textarea>

<h3>Underling model</h3>
<textarea class="textarea" style="width:100%" cols="50" rows="20">
<?php

/**
 * Underling Class (contains self referencing relationships)
 *
 * Transforms employees table into a Underling object.
 *
 * @licence 	MIT Licence
 * @category	Models
 * @author  	Simon Stenhouse
 * @link    	http://stensi.com
 */
class Underling extends Employee
{
	var $has_one = array("supervisor");

	/**
	 * Constructor
	 *
	 * Initialize DataMapper.
	 */
	function Underling()
	{
		parent::Employee();
	}

	// --------------------------------------------------------------------

	/**
	 * Get (overload)
	 *
	 * Get objects.
	 *
	 * @access	public
	 * @param	int or array
	 * @return	bool
	 */
	function get($limit = NULL, $offset = NULL)
	{
		$position = empty($this->position) ? 'Underling' : $this->position;

		$this->where('position', $position);

		return parent::get($limit, $offset);
	}
}

/* End of file underling.php */
/* Location: ./application/models/underling.php */

</textarea>

<p>I recommend trying out the Self Referencing Relationship example in the included <a href="examples.html">Usage Examples</a> to see it in action.</p>

<br />

<p>Now that you have a better understanding of the relationship types, you can continue on to read <a href="settingrelations.html">Setting up Relationships</a>.</p>


</div>
<!-- END CONTENT -->


<div id="footer">
<p>
Previous Topic:&nbsp;&nbsp;<a href="prefix.html">Setting up Table Prefixes</a>
&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
<a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
<a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
Next Topic:&nbsp;&nbsp;<a href="settingrelations.html">Setting up Relationships</a>
</p>
<p><a href="http://stensi.com">DataMapper</a> &nbsp;&middot;&nbsp; Copyright &#169; 2008 &nbsp;&middot;&nbsp; <a href="http://stensi.com/">Simon Stenhouse</a></p>
<p><a href="http://codeigniter.com">CodeIgniter</a> &nbsp;&middot;&nbsp; Copyright &#169; 2006-2008 &nbsp;&middot;&nbsp; <a href="http://ellislab.com/">Ellislab, Inc.</a></p>
</div>

<script type="text/javascript" src="../js/mootools.js"></script>
<script type="text/javascript" src="../js/menu.js"></script>
<script type="text/javascript">
<!--
	window.addEvent('domready', function() {

		// Create Menu
		var menu = new Menu({
			basepath: '../',
			pagepath: ''
		});

	});	
//-->
</script>
</body>
</html>